import { DB_NAME } from '@/uni_modules/stars-UniTS-SQLite-ORM/components/stars-UniTS-SQLite-ORM/dbOrm/config/dbconfig';
import { executeSql, selectSql } from '@/uni_modules/stars-UniTS-SQLite-ORM/components/stars-UniTS-SQLite-ORM/dbOrm/db/SqliteHelper';
import { BaseModel } from '@/uni_modules/stars-UniTS-SQLite-ORM/components/stars-UniTS-SQLite-ORM/dbOrm/model/BaseModel';
import { PageModel } from '@/uni_modules/stars-UniTS-SQLite-ORM/components/stars-UniTS-SQLite-ORM/dbOrm/model/PageModel';
import { ISqliteService } from '@/uni_modules/stars-UniTS-SQLite-ORM/components/stars-UniTS-SQLite-ORM/dbOrm/service/ISqliteService';

export class SqliteServiceImpl<T extends BaseModel> implements ISqliteService {

	// 获取表名称
	private getTableName<T>(modelOrConstructor : T | (new () => T)) : string {
		if (typeof modelOrConstructor === 'function') {
			// 对于构造函数，直接使用 constructor.name
			return (modelOrConstructor as new () => T).name.toLowerCase();
		} else {
			// 对于实例，使用 Object.getPrototypeOf(instance).constructor.name
			return Object.getPrototypeOf(modelOrConstructor as T).constructor.name.toLowerCase();
		}
	}

	// 获取主键名称
	private getPrimaryKey<T>(modelOrConstructor : T | (new () => T)) : string | undefined {
		let metadata : any;
		if (typeof modelOrConstructor === 'function') {
			metadata = (modelOrConstructor as new () => T).prototype.metadata;
		} else {
			metadata = Object.getPrototypeOf(modelOrConstructor).constructor.prototype.metadata;
		}
		if (metadata) {
			for (const property in metadata) {
				if (metadata[property].primaryKey) {
					return property;
				}
			}
		}
		return undefined;
	}



	// 辅助方法：将对象属性转换为 SQL 语句中的列和值
	private getColumnsAndValues(model : T) : { columns : string, values : string } {
		const columns = [];
		const values = [];
		for (const [key, value] of Object.entries(model)) {
			if (key !== 'tableName' && key !== 'primaryKey' && value !== undefined) {
				columns.push(key);
				values.push(`'${value}'`);
			}
		}
		return {
			columns: columns.join(','),
			values: values.join(',')
		};
	}

	// 辅助方法：将对象属性转换为 SQL 更新语句中的 SET 部分
	private getUpdateSet(model : T) : string {
		const setParts = [];
		for (const [key, value] of Object.entries(model)) {
			if (key !== 'tableName' && key !== 'primaryKey' && value !== undefined) {
				setParts.push(`${key} = '${value}'`);
			}
		}
		return setParts.join(',');
	}

	// 插入数据
	async insert(model : T) : Promise<void> {
		const { columns, values } = this.getColumnsAndValues(model);
		const sql = `INSERT INTO ${this.getTableName(model)} (${columns}) VALUES (${values})`;
		await this.executeSql(sql);
	}

	// 根据主键查询数据
	async selectById(id : any, model : new () => T) : Promise<T> {
		const sql = `SELECT * FROM ${this.getTableName(model)} WHERE ${this.getPrimaryKey(model)} = '${id}'`;
		console.log(sql);
		const result = await this.executeSelect(sql);
		if (result && result.length > 0) {
			return this.mapResultToModel(result[0], model);
		}
		return null;
	}

	// 查询所有数据
	async selectAll(model : new () => T) : Promise<T[]> {
		const sql = `SELECT * FROM ${this.getTableName(model)}`;
		const result = await this.executeSelect(sql);
		return this.mapResultsToModels(result, model);
	}

	// 根据条件查询数据
	async selectByCondition(condition : string, model : new () => T) : Promise<T[]> {
		const sql = `SELECT * FROM ${this.getTableName(model)} WHERE ${condition}`;
		const result = await this.executeSelect(sql);
		return this.mapResultsToModels(result, model);
	}

	// 分页查询数据
	async selectByPage(page : number, size : number, condition ?: string, orderBy ?: string, model : new () => T) : Promise<PageModel> {
		let countSql = `SELECT COUNT(*) as totalCount FROM ${this.getTableName(model)}`;
		if (condition) {
			countSql += ` WHERE ${condition}`;
		}
		const countResult = await this.executeSelect(countSql);
		const totalCount = countResult[0]?.totalCount || 0;

		let sql = `SELECT * FROM ${this.getTableName(model)}`;
		if (condition) {
			sql += ` WHERE ${condition}`;
		}
		if (orderBy) {
			sql += ` ORDER BY ${orderBy}`;
		}
		const offset = (page - 1) * size;
		sql += ` LIMIT ${size} OFFSET ${offset}`;
		const result = await this.executeSelect(sql);
		const data = this.mapResultsToModels(result, model);

		return {
			currentPage: page,
			totalCount: totalCount,
			data: data
		};
	}


	// 更新数据
	async update(model : T) : Promise<void> {
		const setClause = this.getUpdateSet(model);
		const sql = `UPDATE ${this.getTableName(model)} SET ${setClause} WHERE ${this.getPrimaryKey(model)} = '${model[this.getPrimaryKey(model)]}'`;
		await this.executeSql(sql);
	}

	/**
	 * 根据条件更改
	 */
	async updateCondition(model : T, condition : string) : Promise<void> {
		const setClause = this.getUpdateSet(model);
		const sql = `UPDATE ${this.getTableName(model)} SET ${setClause} WHERE ${condition}`;
		await this.executeSql(sql);
	}

	/**
	 * 根据条件更改指定更改SQL
	 */
	async updateSqlCondition(model : T, updateSql : string, condition : string) : Promise<void> {
		const sql = `UPDATE ${this.getTableName(model)} SET ${updateSql} WHERE ${condition}`;
		await this.executeSql(sql);
	}

	// 根据主键删除数据
	async deleteById(id : any, model : new () => T) : Promise<void> {
		const sql = `DELETE FROM ${this.getTableName(model)} WHERE ${this.getPrimaryKey(model)} = '${id}'`;
		await this.executeSql(sql);
	}

	// 根据条件删除数据
	// @Transactional
	async deleteByCondition(condition : string, model : new () => T) : Promise<void> {
		const sql = `DELETE FROM ${this.getTableName(model)} WHERE ${condition}`;
		await this.executeSql(sql);
	}

	async sqlRun(sql : string) : Promise<void> {
		await this.executeSql(sql);
	}

	// 辅助方法：将查询结果映射为实体对象
	private mapResultToModel(result : any, model : new () => T) : T {
		const instance = new model();
		for (const [key, value] of Object.entries(result)) {
			instance[key] = value;
		}
		return instance;
	}

	// 辅助方法：将查询结果列表映射为实体对象列表
	private mapResultsToModels(results : any[], model : new () => T) : T[] {
		const list : T[] = [];
		for (const result of results) {
			list.push(this.mapResultToModel(result, model));
		}
		return list;
	}

	// 执行查询操作
	private async executeSelect(sql : string) : Promise<any[]> {
		try {
			// console.log("执行查询sql：", sql);
			// await openSqlite(DB_NAME, this.dbPath);
			const result = await selectSql(DB_NAME, sql);
			return result;
		} catch (error) {
			console.error(`Error executing select query: ${sql}`, error);
			throw error;
		}
	}

	// 执行 SQL 操作
	private async executeSql(sql : string) : Promise<void> {
		try {
			// console.log("执行sql：", sql);
			// await openSqlite(DB_NAME, this.dbPath);
			await executeSql(DB_NAME, sql);
		} catch (error) {
			console.error(`Error executing SQL: ${sql}`, error);
			throw error;
		}
	}
}